package com.niguang.work.show.common.util;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * AES128位对称加密类，该类参数需要16位字符串秘钥及待加/解密字符串
 */
public class AES128Util {

    /**
     * 定义一个16位初始向量，可增加加密算法的强度
     */
    private static final String IV_STRING = "HUI_JIAN_YUAN_IV";

    /**
     * 必须为16位
     */
    private static final String KEY = "HUI_JIA_YUAN_AES";

    /**
     * <p class="detail">
     * 功能：AES128加密方法
     *
     * @param content 待加密内容
     * @return 加密后的字符串（结果已经过base64加密）
     * @throws Exception
     */
    public static String encryptAES(String content)
            throws Exception {
        byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
        // 注意，为了能与 iOS 统一
        // 这里的 key 不可以使用 KeyGenerator、SecureRandom、SecretKey 生成
        byte[] enCodeFormat = KEY.getBytes();
        SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
        byte[] initParam = IV_STRING.getBytes();
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
        // 指定加密的算法、工作模式和填充方式
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        byte[] encryptedBytes = cipher.doFinal(byteContent);
        // 同样对加密后数据进行 base64 编码
        return Base64.encodeBase64String(encryptedBytes);
    }

    /**
     * 功能：解密函数
     *
     * @param content 待解密字符串
     * @return
     * @throws Exception
     */
    public static String decryptAES(String content)
            throws Exception {
        // 先base64 解码
        byte[] encryptedBytes = Base64.decodeBase64(content);
        byte[] enCodeFormat = KEY.getBytes();
        SecretKeySpec secretKey = new SecretKeySpec(enCodeFormat, "AES");
        //使用CBC模式，需要一个向量iv，可增加加密算法的强度
        byte[] initParam = IV_STRING.getBytes();
        IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
        //"算法/模式/补码方式"
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        byte[] result = cipher.doFinal(encryptedBytes);
        if (result.length == 0) {
            throw new IllegalBlockSizeException();
        }
        return new String(result, StandardCharsets.UTF_8);
    }

    /**
     * 测试函数
     */
    public static void main(String[] args) throws Exception {
        String content = "530328199104150917";
        //必须为16位
        String enstring = encryptAES(content);
        String destring = decryptAES(enstring);
        System.out.println("原始字符串：" + content);
        System.out.println("加密后字符串：" + enstring);
        System.out.println("长度：" + enstring.length());
        System.out.println("解密后字符串：" + destring);

    }
}
